#pragma once

#include <linux/hrtimer.h>

/* The CPU is in the tick idle mode */
#define TS_FLAG_INIDLE BIT(0)
/* The idle tick has been stopped */
#define TS_FLAG_STOPPED BIT(1)
/*
 * Indicator that the CPU is actively in the tick idle mode;
 * it is reset during irq handling phases.
 */
#define TS_FLAG_IDLE_ACTIVE BIT(2)
/* CPU was the last one doing do_timer before going idle */
#define TS_FLAG_DO_TIMER_LAST BIT(3)
/* NO_HZ is enabled */
#define TS_FLAG_NOHZ BIT(4)
/* High resolution tick mode */
#define TS_FLAG_HIGHRES BIT(5)

struct tick_sched
{
    unsigned long flags;

    /* Tick handling */
    struct hrtimer sched_timer;
    ktime_t last_tick;
    ktime_t next_tick;
    unsigned long idle_jiffies;
    ktime_t idle_waketime;
    unsigned int got_idle_tick;

    /* Tick stop */
    u64 timer_expires_base;
    u64 timer_expires;
    u64 next_timer;
    ktime_t idle_expires;
    unsigned long last_jiffies;
    unsigned long idle_calls;
    unsigned long idle_sleeps;
};

struct tick_sched *this_cpu_tick_sched(void);

static inline void tick_sched_flag_set(struct tick_sched *ts, unsigned long flag)
{
	ts->flags |= flag;
}

static inline int tick_sched_flag_test(struct tick_sched *ts, unsigned long flag)
{
    return !!(ts->flags & flag);
}

static inline void tick_sched_flag_clear(struct tick_sched *ts, unsigned long flag)
{
	ts->flags &= ~flag;
}

#ifdef CONFIG_NO_HZ_COMMON
void tick_nohz_activate(struct tick_sched *ts);
#else
static inline void tick_nohz_activate(struct tick_sched *ts) {}
#endif

u64 get_jiffies_update(unsigned long *basej);
void tick_do_update_jiffies64(struct tick_sched *ts, ktime_t now);
